const Sequelize = require('sequelize');
var merge = require('lodash.merge');
const uuid = require('node-uuid');

const config = require('../config');
const sqlConfig = require("../config").sqlConfig

function generateId() {
    return uuid.v4();
}

var sequelize = new Sequelize(sqlConfig.database, sqlConfig.user, sqlConfig.password, {
    host: sqlConfig.host,
    dialect: 'mysql',
    pool: {
        max: 5,
        min: 0,
        idle: 10000
    }
});

const ID_TYPE = Sequelize.STRING(50);
/**
 * 每个Model必须遵守一套规范：
 *  统一主键，名称必须是id，类型必须是STRING(50)；
 *  主键可以自己指定，也可以由框架自动生成（如果为null或undefined）；
 *  所有字段默认为NOT NULL，除非显式指定；
 *  统一timestamp机制，每个Model必须有createdAt、updatedAt和version，分别记录创建时间、修改时间和版本号。其中，createdAt和updatedAt以BIGINT存储时间戳，最大的好处是无需处理时区，排序方便。version每次修改时自增。
 */
function defineModel(name, attributes, ops={}) {
    var attrs = {};
    for (let key in attributes) {
        let value = attributes[key];
        if (typeof value === 'object' && value['type']) {
            value.allowNull = value.allowNull || false;
            attrs[key] = value;
        } else {
            attrs[key] = {
                type: value,
                allowNull: false
            };
        }
    }
    attrs.id = {
        type: ID_TYPE,
        primaryKey: true
    };
    attrs.createdAt = {
        type: Sequelize.BIGINT,
        allowNull: false
    };
    attrs.updatedAt = {
        type: Sequelize.BIGINT,
        allowNull: false
    };
    attrs.version = {
        type: Sequelize.BIGINT,
        allowNull: false
    };
    let hooks = {
        beforeValidate: function (obj) {
            let now = Date.now();
            if (obj.isNewRecord) {
                console.log('will create entity...' + obj);
                if (!obj.id) {
                    obj.id = generateId();
                }
                obj.createdAt = now;
                obj.updatedAt = now;
                obj.version = 0;
            } else {
                console.log('will update entity...');
                obj.updatedAt = now;
                obj.version++;
            }
        }
    }
    
    return sequelize.define(name, attrs, merge({
        tableName: name,
        timestamps: false,
        hooks: hooks
    },ops));
}

const TYPES = ['STRING', 'INTEGER', 'BIGINT', 'TEXT', 'DOUBLE', 'DATEONLY', 'BOOLEAN'];

var exp = {
    defineModel: defineModel,
    sync: () => {
        // only allow create ddl in non-production environment:
        if (process.env.NODE_ENV !== 'production') {
            //基于sequelize自动创建表//【！！注意 首次执行完请注释掉该段代码 ！！】
            console.log(sequelize.models)
            sequelize.sync({
                force: true, //是否清空数据库表
            }).then(function () {
                console.log('ok');
            });
        } else {
            throw new Error('Cannot sync() when NODE_ENV is set to \'production\'.');
        }
    }
};

for (let type of TYPES) {
    exp[type] = Sequelize[type];
}

exp.ID = ID_TYPE;
exp.generateId = generateId;
module.exports = exp;